﻿using A.M.ETO;
using A.M.Storage.Application;
using A.M.Storage.I_Infrastruecure;
using AutoMapper;
using DotNetCore.CAP;
using Hangfire;
using Newtonsoft.Json;
using O.M.Production.Application.IService;
using O.M.Production.Domain.DTO;
using O.M.Production.Domain.DTO.Produce_work_order;
using O.M.Production.Domain.Entity;
using O.M.Production.ErrorCodeEnum;
using O.M.Production.Infrastuecure.IRepository;
using O.M.Production.Infrastuecure.Repository;
using Public_Class_Library;
using Q.M.Sell.Doamin.Entity;
using SqlSugar;
using SqlSugar.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using W.M.Materiel.Infrastruecure.DTO;
using static O.M.Production.Domain.EnumModel;

namespace O.M.Production.Application.Service
{
    /// <summary>
    /// 生产工单服务接口实现类
    /// </summary>
    public class produce_work_order_Service : BaseServices<produce_work_order, string>, I_produce_work_order_Service
    {
        private readonly I_quality_inspection_report_Repository _quality_inspection_report_repository;
        private readonly I_quality_inspection_management_Repository _quality_inspection_management_repository;
        // private readonly IBackgroundJobClient _jobClient;
        private readonly ICapPublisher _capPublisher;
        private readonly IMapper _mapper;
        private readonly I_produce_work_order_Repository _produce_work_order_Repository;
        private readonly I_working_procedure_Repository _working_procedure_Repository;
        private readonly Cross_service_Helper cross_Service_Helper;
        public produce_work_order_Service(I_produce_work_order_Repository produce_Work_Order_Repository, IMapper mapper, I_working_procedure_Repository working_procedure_Repository, ICapPublisher capPublisher/*, IBackgroundJobClient jobClient*/, Cross_service_Helper cross_Service_Helper, I_quality_inspection_management_Repository quality_inspection_management_repository, I_quality_inspection_report_Repository quality_inspection_report_repository) : base(produce_Work_Order_Repository)
        {
            _produce_work_order_Repository = produce_Work_Order_Repository;
            _mapper = mapper;
            _working_procedure_Repository = working_procedure_Repository;
            _capPublisher = capPublisher;
            // _jobClient = jobClient;
            this.cross_Service_Helper = cross_Service_Helper;
            _quality_inspection_management_repository = quality_inspection_management_repository;
            _quality_inspection_report_repository = quality_inspection_report_repository;
        }
        /// <summary>
        /// 分页查询-生产工单
        /// </summary>
        /// <param name="PWOId_Name">工单编号或名称</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="pageIndex">页码</param>
        /// <returns>统一返回格式</returns>
        public async Task<ApiResult> Get_produce_work_order(string? PWOId_Name, int pageSize, int pageIndex)
        {
            try
            {
                ApiResult apiResult = new ApiResult();
                Expression<Func<produce_work_order, bool>> whereidname = i => true;
                if (!string.IsNullOrEmpty(PWOId_Name))
                {
                    whereidname = i => i.work_order_id.Contains(PWOId_Name) || i.work_order_name.Contains(PWOId_Name);
                }
                var list = await _produce_work_order_Repository.GetShowQueryableAsync(pageSize, pageIndex, whereidname);
                apiResult.Data = list.Data.OrderByDescending(x => x.work_order_id).ToList();
                apiResult.totalCount = list.TotalCount;
                apiResult.pageCount = list.PageCount;
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }
        /// <summary>
        /// 查实单个工单实体-反填
        /// </summary>
        /// <param name="produce_work_order_id">工单编号</param>
        /// <returns>统一返回格式</returns>                                           
        public async Task<ApiResult> Get_produce_work_order_Model(string? work_order_id)
        {
            try
            {
                ApiResult apiResult = new ApiResult();
                var produce_work_order = await _produce_work_order_Repository.GetShowObjAsync(x => x.work_order_id == work_order_id);
                var produce_work_order_DTO = _mapper.Map<produce_work_order_DTO>(produce_work_order);
                var working_procedure = await _working_procedure_Repository.GetShowInforAsync(x => x.work_order_id == work_order_id);
                if (working_procedure.Count != 0)
                {
                    produce_work_order_DTO.working_Procedure_DTOs = _mapper.Map<List<working_procedure_DTO>>(working_procedure);
                }
                if (produce_work_order_DTO != null)
                {
                    apiResult.Code = 200;
                    apiResult.Message = "返回成功";
                    apiResult.Data = produce_work_order_DTO;
                }
                else
                {
                    apiResult.Code = 500;
                    apiResult.Message = "返回失败";
                }
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }

        /// <summary>
        /// 添加生产工单
        /// </summary>
        /// <param name="produce_Work_Order_DTO">生产工单DTO</param>
        /// <returns>统一返回格式</returns>
        public async Task<ApiResult> Post_Produce_Work_Order_Add(produce_work_order_DTO produce_Work_Order_DTO)
        {
            ApiResult apiResult = new ApiResult();
            try
            {
                //开启事务
                _produce_work_order_Repository.BeginTranInfor();
                //判断不能为空
                if (produce_Work_Order_DTO.working_Procedure_DTOs == null || produce_Work_Order_DTO.working_Procedure_DTOs.Count == 0 || produce_Work_Order_DTO == null)
                {
                    apiResult.Code = 500;
                    apiResult.Message = "添加的数据有空值";
                    _produce_work_order_Repository.RollbackTranInfor();
                    return apiResult;
                }
                var produce_Work_Order = _mapper.Map<produce_work_order>(produce_Work_Order_DTO);
                var working_Procedure = _mapper.Map<List<working_procedure>>(produce_Work_Order_DTO.working_Procedure_DTOs);
                produce_Work_Order._add_name = produce_Work_Order_DTO._add_name;
                produce_Work_Order._add_time = DateTime.Now;
                var res = await _produce_work_order_Repository.AddInfor_Async(produce_Work_Order);
                //if (res > 0)
                //{
                //    //添加成功需要传一个消息队列  传递哪个模块 还有编号
                //    string numberName = "工单系统-" + produce_Work_Order_DTO.Work_order_Id;
                //    _capPublisher.Publish("GetNewNumber", numberName);
                //}
                foreach (var item in working_Procedure)
                {
                    item.work_order_id = produce_Work_Order_DTO.work_order_id;
                }
                var res1 = await _working_procedure_Repository.AddInfor_Batch_Async(working_Procedure);
                if (res1 > 0 && res > 0)
                {
                    apiResult.Code = 200;
                    apiResult.Message = "添加成功";
                    //添加成功需要传一个消息队列  传递哪个模块 还有编号
                    string numberName = "工单系统-" + produce_Work_Order_DTO.work_order_id;
                    _capPublisher.Publish("GetNewNumber", numberName);
                    //每天早上4点执行
                    RecurringJob.AddOrUpdate("myrecurringjob", () => UpdNum(produce_Work_Order_DTO.work_order_id), "0 10 * * *");
                    //添加质检管理
                    quality_inspection_management quality_Inspection_Management = new quality_inspection_management();
                    quality_Inspection_Management.quality_inspection_work_order_Id = produce_Work_Order_DTO.work_order_id;
                    quality_Inspection_Management.quality_inspection_work_order_name = produce_Work_Order_DTO.work_order_name;
                    quality_Inspection_Management.source_work_order = produce_Work_Order_DTO.work_order_id;
                    quality_Inspection_Management.production_product = produce_Work_Order_DTO.production_product;
                    quality_Inspection_Management.quality_inspection_department = produce_Work_Order_DTO.department;
                    quality_Inspection_Management.person_in_charge = produce_Work_Order_DTO.person_in_charge;
                    quality_Inspection_Management.process_quantity = produce_Work_Order_DTO.process_quantity;
                    quality_Inspection_Management.number_of_work_reports = produce_Work_Order_DTO.number_of_work_reports;
                    quality_Inspection_Management.quality_inspection_times = 0;
                    quality_Inspection_Management.remarks = produce_Work_Order_DTO.remarks;
                    quality_Inspection_Management.attachment = produce_Work_Order_DTO.attachment;
                    quality_Inspection_Management._add_time = DateTime.Now;
                    quality_Inspection_Management._add_name = produce_Work_Order_DTO._add_name;
                    _quality_inspection_management_repository.AddInfor(quality_Inspection_Management);
                    _produce_work_order_Repository.CommitTranInfor();
                }
                else
                {
                    apiResult.Code = 500;
                    apiResult.Message = "添加失败";
                    _produce_work_order_Repository.RollbackTranInfor();
                }
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                _produce_work_order_Repository.RollbackTranInfor();
                throw;
            }
        }
        /// <summary>
        /// 批量删除-生产工单
        /// </summary>
        /// <param name="produce_Work_Order_DTOs">生产工单DTO</param>
        /// <returns>统一返回格式</returns>
        public async Task<ApiResult> Post_Batch_Del_Work_Order_Add(List<produce_work_order_DTO> produce_Work_Order_DTOs)
        {
            try
            {
                _produce_work_order_Repository.BeginTranInfor();
                var produce_Work_Order = _mapper.Map<List<produce_work_order>>(produce_Work_Order_DTOs);
                var res = await _produce_work_order_Repository.DelInfor_Batch_Async(produce_Work_Order);
                foreach (var item in produce_Work_Order_DTOs)
                {
                    var working_procedure = await _working_procedure_Repository.GetShowInforAsync(x => x.work_order_id == item.work_order_id);
                    var res1 = await _working_procedure_Repository.DelInfor_Batch_Async(working_procedure);
                }
                ApiResult apiResult = new ApiResult();
                if (res > 0)
                {
                    apiResult.Code = 200;
                    apiResult.Message = "删除成功";
                    _produce_work_order_Repository.CommitTranInfor();
                }
                else
                {
                    apiResult.Code = 500;
                    apiResult.Message = "删除失败";
                    _produce_work_order_Repository.RollbackTranInfor();
                }
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                _produce_work_order_Repository.RollbackTranInfor();
                throw;
            }
        }
        /// <summary>
        /// 修改-生产工单
        /// </summary>
        /// <param name="produce_Work_Order_DTO">生产工单DTO</param>
        /// <returns>统一返回格式</returns>
        public async Task<ApiResult> Post_Upd_Produce_Work_Order(produce_work_order_DTO produce_Work_Order_DTO)
        {
            try
            {
                _produce_work_order_Repository.BeginTranInfor();
                var produce_Work_Order = _mapper.Map<produce_work_order>(produce_Work_Order_DTO);
                var working_procedure = _mapper.Map<List<working_procedure>>(produce_Work_Order_DTO.working_Procedure_DTOs).Where(x => x.work_order_id == produce_Work_Order_DTO.work_order_id).ToList();
                var res = await _produce_work_order_Repository.UpdInfor_Async(produce_Work_Order);
                var res1 = await _working_procedure_Repository.DelInfor_Batch_Async(working_procedure);
                var workingList = _mapper.Map<List<working_procedure>>(produce_Work_Order_DTO.working_Procedure_DTOs);
                foreach (var item in workingList)
                {
                    item.work_order_id = produce_Work_Order.work_order_id;
                }
                var res2 = await _working_procedure_Repository.AddInfor_Batch_Async(workingList);
                ApiResult apiResult = new ApiResult();
                if (res > 0 && res1 > 0 && res2 > 0)
                {
                    apiResult.Code = 200;
                    apiResult.Message = "修改成功";
                    _produce_work_order_Repository.CommitTranInfor();
                }
                else
                {
                    apiResult.Code = 500;
                    apiResult.Message = "修改失败";
                    _produce_work_order_Repository.RollbackTranInfor();
                }
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                _produce_work_order_Repository.RollbackTranInfor();
                throw;
            }
        }
        //public ApiResult DelHangfire AddInfor()

        /// <summary>
        /// 修改完工数量
        /// </summary>
        /// <param name="Id"></param>
        public async Task UpdNum(string? Id)
        {
            try
            {
                produce_work_order? res = _produce_work_order_Repository.GetShowObj(x => x.work_order_id == Id);


                //先或获取产品
                var Url2 = "http://10.31.59.21:8087/api/Bom_item_relation_table/GetBom_Item_Relation_Table";
                var Bom = await cross_Service_Helper.Get(Url2);
                var Bom_List = JsonConvert.DeserializeObject<List<Bom_item_relation_tableDTO>>(Bom);
                var ges = Bom_List.Where(c => c.product_material_numbers == res.work_order_id).FirstOrDefault();

                if (ges != null)
                {
                    //判断是否生产完毕 计算公式(合格数量 + 不良数量 == 预计总量)
                    if (res.designed_output > res.qualified_quantity + res.bad_quantity)
                    {
                        //如果不相等 加数量
                        //获取工作日表
                        var work = "http://10.31.59.5:8001/api/Working_hours/GetShowInforAsyncWork";
                        var Work = await cross_Service_Helper.Get(work);
                        var Work_List = JsonConvert.DeserializeObject<List<Working_hoursDTO>>(Work);

                        //今日下的工单 第二天才去执行
                        var today = DateTime.Today.DayOfWeek;
                        var getDay = "";
                        switch (today)
                        {
                            case DayOfWeek.Sunday:
                                getDay = "星期日";
                                break;
                            case DayOfWeek.Monday:
                                getDay = "星期一";
                                break;
                            case DayOfWeek.Tuesday:
                                getDay = "星期二";
                                break;
                            case DayOfWeek.Wednesday:
                                getDay = "星期三";
                                break;
                            case DayOfWeek.Thursday:
                                getDay = ("星期四");
                                break;
                            case DayOfWeek.Friday:
                                getDay = ("星期五");
                                break;
                            case DayOfWeek.Saturday:
                                getDay = ("星期六");
                                break;
                        }
                        var getworklist = Work_List.Where(c => c.work_week == getDay).FirstOrDefault();
                        //生成上午的定时任务
                        var moenyarr = getworklist.work_morning.Split(" - ");
                        //生成CRON表达式 标识从早上几点开始 到几点结束 每15分钟执行一次
                        string moenycron = "";

                        moenycron = $"*/15 {Convert.ToInt32(moenyarr[0].Split(":")[0])}-{Convert.ToInt32(moenyarr[1].Split(":")[0])} * * *";

                        //下午的
                        RecurringJob.AddOrUpdate(Id, () => InforUpdNum(Id), moenycron);

                        //生成下午的定时任务
                        var aufgar = getworklist.work_afternoon.Split(" - ");
                        //生成CRON表达式 标识从下午几点开始 每15分钟执行一次
                        string aufgararr = "";
                        moenycron = $"*/15 {Convert.ToInt32(aufgar[0].Split(":")[0])}-{Convert.ToInt32(aufgar[1].Split(":")[0])} * * *";

                        RecurringJob.AddOrUpdate(Id + "1", () => InforUpdNum(Id), aufgararr);
                    }
                }


            }
            catch (Exception)
            {

                throw;
            }

        }

        /// <summary>
        /// 生成产量
        /// </summary>
        /// <param name="id"></param>
        public async Task InforUpdNum(string? id)
        {
            try
            {
                _produce_work_order_Repository.BeginTranInfor();

                produce_work_order? res = await _produce_work_order_Repository.GetShowObjAsync(c => c.work_order_id == id);

                //先或获取 BOM 点的每15分钟产量
                var Url2 = "http://10.31.59.21:8087/api/Bom_item_relation_table/GetBom_Item_Relation_Table";
                var Bom = await cross_Service_Helper.Get(Url2);
                var Bom_List = JsonConvert.DeserializeObject<List<Bom_item_relation_tableDTO>>(Bom);
                var ges = Bom_List.Where(c => c.product_material_numbers == res.work_order_id).FirstOrDefault();
                var countres = Convert.ToInt32(Math.Ceiling(ges.TimeNum * 1.0 / 15));
                //计算不合格率有多少
                var buhg = Convert.ToInt32(Math.Ceiling((res.qualified_quantity + res.bad_quantity) * 1.0 / 100));
                if ((res.qualified_quantity + buhg) >= res.designed_output)
                {
                    res.designed_output += res.bad_quantity + res.qualified_quantity;
                    RecurringJob.RemoveIfExists(id);
                    RecurringJob.RemoveIfExists(id + "1");
                }
                else
                {
                    res.qualified_quantity += res.qualified_quantity + res.bad_quantity - buhg;
                }
                await _produce_work_order_Repository.UpdInfor_Async(res);
                _produce_work_order_Repository.CommitTranInfor();
            }
            catch (Exception)
            {
                _produce_work_order_Repository.RollbackTranInfor();
                throw;
            }
        }

        /// <summary>
        /// 修改状态-工序流程
        /// </summary>
        /// <param name="Wid">工单编号</param>
        /// <returns>0关闭 1报工 2开工 3完成 4重启</returns>
        public async Task<ApiResult> Put_Upd_State_Work_Order(int? Wid, int State, produce_work_order_DTO produce_Work_Order_DTO)
        {
            try
            {
                _working_procedure_Repository.BeginTranInfor();
                ApiResult apiResult = new ApiResult();
                var res = await _working_procedure_Repository.GetShowObjAsync(x => x.working_procedure_id == Wid);
                res.state = State;
                var res1 = _working_procedure_Repository.UpdInfor(res);

                if (res1 > 0)
                {
                    apiResult.Code = 200;
                    switch (State)
                    {
                        case 1:
                            apiResult.Message = "报工成功";
                            var quality_inspection_management = await _quality_inspection_management_repository.GetShowObjAsync(x => x.quality_inspection_work_order_Id == produce_Work_Order_DTO.work_order_id);
                            quality_inspection_management.number_of_work_reports++;
                            await _quality_inspection_management_repository.UpdInfor_Async(quality_inspection_management);
                            _quality_inspection_management_repository.CommitTranInfor();
                            break;
                        case 2:
                            apiResult.Message = "开工成功";
                            res.actual_start_time = DateTime.Now;
                            await _working_procedure_Repository.UpdInfor_Async(res);
                            _working_procedure_Repository.CommitTranInfor();
                            break;
                        case 3:
                            apiResult.Message = "完成成功";
                            res.actual_end_time = DateTime.Now;
                            await _working_procedure_Repository.UpdInfor_Async(res);
                            quality_inspection_report quality_Inspection_Report = new quality_inspection_report();
                            quality_Inspection_Report.quality_inspection_work_order_Id = res.work_order_id;
                            quality_Inspection_Report.working_procedure_code = res.working_id;
                            quality_Inspection_Report.process_flow_id = res.process_flow_id;
                            quality_Inspection_Report.working_procedure_name = res.working_name;
                            quality_Inspection_Report.process_flow = res.process_flow;
                            quality_Inspection_Report.manufacturing_procedure = res.job_order;
                            quality_Inspection_Report.production_department = Produce_Department.生产部门一.ToString();
                            quality_Inspection_Report.person_in_charge = res.person_in_charge.ToString();
                            quality_Inspection_Report.report_for_work_date = DateTime.Now;
                            quality_Inspection_Report.completed_quantity = res.completed_quantity;
                            quality_Inspection_Report.producer = Produce_Personnel.王麻子.ToString();
                            quality_Inspection_Report.department = res.department.ToString();
                            quality_Inspection_Report.newspaper_worker = produce_Work_Order_DTO._upd_name;
                            await _quality_inspection_report_repository.AddInfor_Async(quality_Inspection_Report);
                            _working_procedure_Repository.CommitTranInfor();
                            break;
                        case 4:
                            apiResult.Message = "重启成功";
                            _produce_work_order_Repository.CommitTranInfor();
                            break;
                        default:
                            apiResult.Message = "关闭成功";
                            _produce_work_order_Repository.CommitTranInfor();
                            break;
                    }
                }
                return apiResult;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                _working_procedure_Repository.RollbackTranInfor();
                throw;
            }
        }
    }
}
